package com.wyj.server;

import com.wyj.connector.Connector;
import com.wyj.connector.CustomerThreadFactory;
import com.wyj.mapper.MappedHost;
import com.wyj.mapper.Mapper;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * TODO: xml解析器，解析server.xml
 *
 * @author wuyijie
 * @date 2021/12/13 21:42
 */
public class Digester {
    /**
     * 存储解析到的所有的service组件。后续进行遍历初始化、启动
     * */
    public static final List<Service> SERVICE_LIST = new ArrayList<>();
    /**
     * 存储解析到的所有的service组件。后续进行使用
     * */
    public static final Map<String, Service> SERVICE_MAP = new HashMap<>();
    /**
     * 全局mapper组件
     * */
    public static final Mapper MAPPER = new Mapper(new HashMap<String, MappedHost>());

    /**
     * TODO: 解析server.xml，配置tomcat的组件
     *
     * @author wuyijie
     * @date 2021/12/16 5:09 下午
     */
    static void load() {
        InputStream resourceAsStream = Digester.class.getClassLoader().getResourceAsStream("server.xml");
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();

            List<Node> serviceNodeList = rootElement.selectNodes("./Service");
            for (Node serviceNode : serviceNodeList) {
                Element serviceElement = (Element) serviceNode;
                String serviceName = serviceElement.attributeValue("name");
                Service service = new Service();
                service.setName(serviceName);

                //<connector>解析
                List<Node> connectorNodeList = serviceElement.selectNodes("./Connector");
                List<Connector> connectorList = new ArrayList<>();
                for (Node connectorNode : connectorNodeList) {
                    Element connectorElement = (Element) connectorNode;
                    Connector connector = new Connector(connectorElement.attributeValue("port"));
                    connector.setServiceName(serviceName);
                    connectorList.add(connector);
                }
                service.setConnectorList(connectorList);


                //<Engine>解析
                Node engineNode = serviceElement.selectSingleNode("./Engine");
                Element engineElement = (Element) engineNode;
                String engineName = engineElement.attributeValue("name");
                String engineDefaultHost = engineElement.attributeValue("defaultHost");
                Engine engine = new Engine(engineName, engineDefaultHost);
                //<Host>解析
                List<Node> hostNodeList = engineElement.selectNodes("./Host");
                List<Host> hosts = new ArrayList<>();
                for (Node hostNode : hostNodeList) {
                    Element hostElement = (Element) hostNode;
                    String hostName = hostElement.attributeValue("name");
                    String hostAppBase = hostElement.attributeValue("appBase");
                    Host host = new Host(hostName, hostAppBase);

                    // <Context>解析
                    List<Context> contextList = new ArrayList<>();
                    List<Node> contextNodeList = hostElement.selectNodes("./Context");

                    for (Node contextNode : contextNodeList) {
                        Element contextElement = (Element) contextNode;
                        String contextPath = contextElement.attributeValue("path");
                        String contextDocBase = contextElement.attributeValue("docBase");

                        Context context = new Context(contextPath, contextDocBase, new HashMap<String,Wrapper>(64));
                        contextList.add(context);
                    }
                    host.setContextList(contextList);
                    hosts.add(host);
                }
                engine.setHostList(hosts);
                service.setEngine(engine);

                //自定义线程池，为每个service设置一个单独的线程池。线程池前缀为tomcat下servcie的名称
                int processors = Runtime.getRuntime().availableProcessors();
                ThreadFactory threadFactory = new CustomerThreadFactory(serviceName);
                ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(processors, processors,
                        60L, TimeUnit.SECONDS,
                        new LinkedBlockingQueue<Runnable>(),
                        threadFactory,
                        new ThreadPoolExecutor.AbortPolicy());
                service.setExecutorService(threadPoolExecutor);

                SERVICE_LIST.add(service);
                SERVICE_MAP.put(serviceName, service);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
            throw new RuntimeException("digester load() 失败了啊啊啊啊啊");
        }

    }


}
